package gw.com.android.app;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.multidex.MultiDex;
import android.util.Log;

import com.gwtsz.gts2.hx.BuildConfig;
import com.gwtsz.gts2.hx.R;
import com.mob.MobSDK;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.smtt.sdk.QbSdk;
import com.tencent.smtt.sdk.TbsListener;
import com.tencent.tinker.loader.app.ApplicationLike;
import com.tendcloud.appcpa.TalkingDataAppCpa;
import com.tendcloud.tenddata.TCAgent;
import com.tinkerpatch.sdk.TinkerPatch;
import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike;
import com.umeng.analytics.MobclickAgent;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import cn.jpush.android.api.JPushInterface;
import gw.com.android.model.ConfigType;
import gw.com.android.model.ConfigUtil;
import gw.com.android.presenter.AdverPagePresenter;
import gw.com.android.presenter.FMPresenter;
import gw.com.android.recovery.RecoveryManager;
import gw.com.android.terminal.AppTerminal;
import gw.com.android.terminal.GTSDataListener;
import gw.com.android.ui.account.LoginActivity;
import gw.com.android.utils.ChannelUtil;
import gw.com.android.utils.ENV;
import gw.com.android.utils.IOUtils;
import gw.com.android.utils.MobclickEventUtlis;
import gw.com.android.utils.PayegisUtil;
import gw.com.android.utils.ServerConnnectUtil;
import www.com.library.app.AppActivities;
import www.com.library.app.ExceptionLogger;
import www.com.library.app.LogService;
import www.com.library.app.Logger;
import www.com.library.util.NetworkMonitor;
import www.com.library.util.StringFormatter;


/**
 * 应用入口，application
 */
public class AppMain extends Application {

    public boolean startFlag = true;
    private static AppMain app = null;
    private int foreActivities = 0;
    private Handler mHandler;

    public AppMain() {
        super();
        app = this;
    }

    public boolean isNight = false;

    /**
     * 設置白天黑夜模式
     */
    public void setThemeMode(Context mContext) {
        Logger.i("isNight == " + isNight);
        if (isNight) {
            mContext.setTheme(R.style.NightTheme);
        } else {
            mContext.setTheme(R.style.DayTheme);
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    /**
     * 切換白天黑夜模式
     */
    public void changedThemeMode(Context mContext, int theme) {
        isNight = theme != R.style.DayTheme;
        mContext.setTheme(theme);
    }

    public Handler getHandler() {
        return mHandler;
    }

    public void onCreate() {
        super.onCreate();
        initTinkerPatch();
        mHandler = new Handler(Looper.getMainLooper());
        Logger.i("AppMain", "新的Application");

        //监听应用中所有Activity的运行情况
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            public void onActivityStopped(Activity activity) {
                foreActivities--;
                Logger.e("ActivityLifecycleCallbacks onActivityStopped " + foreActivities);
                //判断是否在后台
                if (foreActivities == 0 && !isAppOnForeground()) {
                    ServerConnnectUtil.instance().isBackRuning = true;
                    AppTerminal.instance().setBackRunState(true);
                    ServerConnnectUtil.instance().disConnectServer();
                    Logger.e("ActivityLifecycleCallbacks 从前台回到后台");
                    FMPresenter.getInstance().pause();
                }
            }

            public void onActivityStarted(Activity activity) {
                foreActivities++;
                Logger.e("ActivityLifecycleCallbacks onActivityStarted " + foreActivities);

                //从后台回到前台
                if (isAppOnForeground() && ServerConnnectUtil.instance().isBackRuning) {
                    ServerConnnectUtil.instance().isBackRuning = false;
                    ServerConnnectUtil.instance().cancelDisConnectTask();
                    AppTerminal.instance().setBackRunState(false);
                    Logger.e("ActivityLifecycleCallbacks 从后台回到前台");
                    if (NetworkMonitor.hasNetWorkNoToast() && !GTConfig.instance().mHasKickOut
                            && !(activity instanceof LoginActivity)
                            && GTConfig.instance().hasShowMain) {
                        Logger.e("ActivityLifecycleCallbacks 从后台回到前台 进入重连判断方法。。。");
                        ServerConnnectUtil.instance().hasReConnectServer();
                    }
                    AdverPagePresenter.getInstance().onAwake(activity);
                }

            }

            @Override
            public void onActivityCreated(Activity arg0, Bundle arg1) {

            }

            @Override
            public void onActivityDestroyed(Activity arg0) {

            }

            @Override
            public void onActivityPaused(Activity arg0) {

            }

            @Override
            public void onActivityResumed(Activity arg0) {
                Log.d("application", "---- onActivityResumed: " + arg0.toString());
            }

            @Override
            public void onActivitySaveInstanceState(Activity arg0, Bundle arg1) {

            }
        });
        initUMConfig();
    }

    /**
     * 初始化友盟统计配置
     */
    private void initUMConfig() {
        ChannelUtil channelUtil = new ChannelUtil();
        MobclickAgent.UMAnalyticsConfig umAnalyticsConfig = new MobclickAgent.UMAnalyticsConfig(this, getResources().getString(R.string.umeng_appkey), channelUtil.getChannel(this));
        MobclickAgent.startWithConfigure(umAnalyticsConfig);
    }

    /**
     * 初始化应用的一些值
     */
    public void initParam() {
        //友盟禁止默认的页面统计方式
        MobclickAgent.openActivityDurationTrack(false);
        MobclickEventUtlis.MobclickEvent(this, "Start_APP");

        PayegisUtil.initPayEgis(getApp());

        //极光推送
        JPushInterface.setDebugMode(!ENV.isRelease());
        JPushInterface.init(this);

        //TalkingData初始化
        ChannelUtil channelUtil = new ChannelUtil();
        TCAgent.init(this, getAppString(R.string.TD_APP_ID), channelUtil.getChannel(this));
        TCAgent.setReportUncaughtExceptions(false);

        // ad tracking 初始化
        TalkingDataAppCpa.init(this, getAppString(R.string.ad_tracking_id), channelUtil.getChannel(this));

        //本地配置处理
        GTConfig.instance().readPreference(this);
        ConfigUtil.instance();

        if (ENV.isRelease()) {
            // 打线上包时，关闭所有日志输出
            Logger.disableLogger();
        } else {
            //crash日志
            ExceptionLogger.registerException(GTConfig.instance().getRootDirectory());
            CrashReport.initCrashReport(getApplicationContext(), getAppString(R.string.bugly_key_id), false);
            //打印日志文件
            Intent stateService = new Intent(this, LogService.class);
            startService(stateService);
        }

        //日志回收
        if (!GTConfig.instance().getLoginName().equals("")) {
            String uploadUrl = ConfigUtil.instance().mConfigObject.optString(ConfigType.RECOVERY_URL_TAG);
            String checkurl = ConfigUtil.instance().getHttpUrlIp(ConfigType.CONFIG_URL_TAG) + "/api/app/accountConfig";
            String logFilePath = GTConfig.instance().getRootDirectory() + "/clog";
            String zipLogFilePath = GTConfig.instance().getRootDirectory() + "/RecoveryLog.zip";
            String companyIdTag = ConfigUtil.instance().mConfigObject.optString(ConfigType.CHAT_COMPANY_ID_TAG);
            String encryptKey = ConfigUtil.instance().mConfigObject.optString(ConfigType.ENCRYPT_KEY_TAG);
            String companyId = ConfigUtil.instance().mConfigObject.optString(ConfigType.COMPANY_ID_TAG);
            new RecoveryManager(uploadUrl, checkurl, logFilePath, zipLogFilePath, companyIdTag, encryptKey, companyId).checkNeedRecover(GTConfig.instance().getLoginName());
        }
        //连接jni的初始化
        AppTerminal.instance().initTerminal(ConfigUtil.instance().urlJsonStr, GTConfig.instance().getRootDirectory(), getAssets(), "gw/com/android/terminal/GTSDataListener");
        GTSDataListener.instance().subscribe();
        // 初始化跟jni数据沟通对象,设置语言类型,时区
        AppTerminal.instance().addGTSDataListener();
        AppTerminal.instance().setLanguage(GTConfig.instance().getLanguage());
        StringFormatter.instance().initTime(AppTerminal.instance().getZoneType());

        if (!isMonkeyRunning()) {
            //腾讯浏览器注册
            QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

                @Override
                public void onViewInitFinished(boolean arg0) {
                    Log.e("app", " onViewInitFinished is " + arg0);
                }

                @Override
                public void onCoreInitFinished() {

                }
            };
            QbSdk.setTbsListener(new TbsListener() {
                @Override
                public void onDownloadFinish(int i) {
                    Log.d("app", "onDownloadFinish");
                }

                @Override
                public void onInstallFinish(int i) {
                    Log.d("app", "onInstallFinish");
                }

                @Override
                public void onDownloadProgress(int i) {
                    Log.d("app", "onDownloadProgress:" + i);
                }
            });
            // 获取手机厂商
            String carrier = android.os.Build.MANUFACTURER;
            String buidler = getSystemProperty("ro.build.version.incremental");
            Logger.e("buidler = " + buidler + ",carrier = " + carrier);
            if (carrier.equals("Xiaomi")) {
                QbSdk.preInit(getApplicationContext(), cb);
            } else {
                QbSdk.initX5Environment(getApplicationContext(), cb);
            }
        }
        MobSDK.init(this, getString(R.string.mob_share_sdk_app_key), getString(R.string.mob_share_sdk_app_secret));
    }

    public String getSystemProperty(String propName) {
        String line;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + propName);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            line = input.readLine();
            input.close();
        } catch (IOException ex) {
            return null;
        } finally {
            IOUtils.closeSilent(input);
        }
        return line;
    }

    /**
     * Returns true if Monkey is running.
     */
    public boolean isMonkeyRunning() {
        return ActivityManager.isUserAMonkey();
    }

    /**
     * 复制formular.db到sd卡指定路径
     */
    public void copyFormular() {
        String filename = "formular.db";
        String newPath = GTConfig.instance().getRootDirectory();
        try {
            File fileDir = new File(newPath);
            File mFile = new File(newPath + "/" + filename);
            Logger.e("copyFormular::" + mFile.getPath());
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            if (!mFile.exists()) {
                Logger.e("创建文件！！！");
                mFile.createNewFile();
            }
//			FileInputStream fileStream = new FileInputStream(mFile);
            InputStream is = getAssets().open(filename);

            if (mFile.length() < 1) {
                Logger.e("复制formular.db到sd卡指定路径！！！" + mFile.getPath() + mFile.exists());
                FileOutputStream fos = new FileOutputStream(mFile);
                byte[] buffer = new byte[1024];
                int byteCount;
                while ((byteCount = is.read(buffer)) != -1) {// 循环从输入流读取
                    // buffer字节
                    fos.write(buffer, 0, byteCount);// 将读取的输入流写入到输出流
                }
                fos.flush();// 刷新缓冲区
                is.close();
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 程序是否在前台运行,true表示运行在前台，false表示运行在后台
     *
     * @return boolean
     */
    public static boolean isAppOnForeground() {
        ActivityManager activityManager = (ActivityManager) AppMain.getApp()
                .getApplicationContext()
                .getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = AppMain.getApp().getPackageName();

        if (null == activityManager) {
            return false;
        }

        List<RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(packageName)
                    && appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true;
            }
        }
        return false;
    }

    public static boolean isAppRun() {
        ActivityManager activityManager = (ActivityManager) AppMain.getApp()
                .getApplicationContext()
                .getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = AppMain.getApp().getPackageName();

        if (null == activityManager) {
            return false;
        }

        List<RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 返回应用程序句柄
     *
     * @return AppMain
     */
    public static AppMain getApp() {
        return app;
    }

    /**
     * 根据应用对象返回应用中文字
     *
     * @param strId id
     */
    public static String getAppString(int strId) {
        if (null != AppActivities.getSingleton().currentActivity()) {
            return AppActivities.getSingleton().currentActivity().getString(strId);
        }
        return getApp().getString(strId);
    }

    /**
     * 根据应用对象返回应用中文字
     *
     * @param strid      id
     * @param formatArgs 格式化对象
     */
    public static String getAppString(int strid, Object... formatArgs) {
        if (null != AppActivities.getSingleton().currentActivity()) {
            return AppActivities.getSingleton().currentActivity().getString(strid, formatArgs);
        }
        return getApp().getString(strid, formatArgs);
    }

    /**
     * 根据id返回数组
     */
    public static String[] getAppArrayString(int strId) {
        return getApp().getResources().getStringArray(strId);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        Logger.i("======onLowMemory========");
        // activity由系统打开 (是由于手机内存不够,activity在后台被系统回收,再打开时出现的现象)
        // 因为系统加载的所有的Activity不在同一个线程,所以要结束其他线程
        // AppActivities.getSingleton().popAllActivityExceptOne(null);
        // android.os.Process.killProcess(android.os.Process.myPid());
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        /*
         * OnTrimMemory的参数是一个int数值，代表不同的内存状态： TRIM_MEMORY_COMPLETE
         * 80：内存不足，并且该进程在后台进程列表最后一个，马上就要被清理 TRIM_MEMORY_MODERATE
         * 60：内存不足，并且该进程在后台进程列表的中部。 TRIM_MEMORY_BACKGROUND 40：内存不足，并且该进程是后台进程。
         * TRIM_MEMORY_UI_HIDDEN 20：内存不足，并且该进程的UI已经不可见了。 以上4个是4.0增加
         *
         * TRIM_MEMORY_RUNNING_CRITICAL 15：内存不足(后台进程不足3个)，并且该进程优先级比较高，需要清理内存
         * TRIM_MEMORY_RUNNING_LOW 10：内存不足(后台进程不足5个)，并且该进程优先级比较高，需要清理内存
         * TRIM_MEMORY_RUNNING_MODERATE 5：内存不足(后台进程超过5个)，并且该进程优先级比较高，需要清理内存
         * 以上3个是4.1增加
         */
        Logger.i("======onTrimMemory level========" + level);
    }

    /**
     * 判断是否获取了手机权限
     */
    public boolean hasReadPhone() {
        PackageManager pm = getPackageManager();
        return (PackageManager.PERMISSION_GRANTED ==
                pm.checkPermission("android.permission.READ_PHONE_STATE", this.getPackageName()));
    }

    /**
     * 我们需要确保至少对主进程跟patch进程初始化 TinkerPatch
     */
    private void initTinkerPatch() {
        // 我们可以从这里获得Tinker加载过程的信息
        if (BuildConfig.TINKER_ENABLE) {
            ApplicationLike tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
            // 初始化TinkerPatch SDK
            TinkerPatch.init(tinkerApplicationLike
//                new TinkerPatch.Builder(tinkerApplicationLike)
//                    .requestLoader(new OkHttp3Loader())
//                    .build()
            )
                    .reflectPatchLibrary()
                    .setPatchRollbackOnScreenOff(true)
                    .setPatchRestartOnSrceenOff(true)
                    .setFetchPatchIntervalByHours(3);
            // 获取当前的补丁版本
            Log.d("AppMain", "Current patch version is " + TinkerPatch.with().getPatchVersion());

            // fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false)
            // 不同的是，会通过handler的方式去轮询
            TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
        }
    }

}
